package refactoringtechniques;

import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class Main {

    public static void main(String[] args) {
        MainForm mainForm = new MainForm();
    }

    private static class MainForm extends JFrame {
        private JLabel label1 = new JLabel();
        private JLabel label2 = new JLabel();
        private JComboBox codeSmellGroups = new JComboBox();
        private JComboBox codeSmells = new JComboBox();
        private JList refactorings = new JList();

        public MainForm() {
            makeInterface();
        }

        private void makeInterface() {

            Font theFont = new Font(Font.SANS_SERIF, Font.PLAIN, 11);
            Container theContent;

            this.setTitle("Refactoring Techniques");
            this.setSize(442, 300);
            this.setLayout(null);
            this.setVisible(true);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setResizable(false);
            theContent = this.getContentPane();

            label1.setText("Code Smell Group");
            label1.setFont(theFont);
            label1.setLocation(12, 15);
            label1.setSize(92, 13);
            theContent.add(label1);

            label2.setText("Code Smell");
            label2.setFont(theFont);
            label2.setLocation(44, 42);
            label2.setSize(60, 13);
            theContent.add(label2);

            refactorings.setModel(new DefaultListModel());
            refactorings.setFont(theFont);
            refactorings.setLocation(12, 66);
            refactorings.setSize(410, 199);
            theContent.add(refactorings);

            codeSmellGroups.setModel(new DefaultComboBoxModel());
            codeSmellGroups.setFont(theFont);
            codeSmellGroups.setLocation(110, 12);
            codeSmellGroups.setSize(312, 21);
            theContent.add(codeSmellGroups);

            codeSmells.setModel(new DefaultComboBoxModel());
            codeSmells.setFont(theFont);
            codeSmells.setLocation(110, 39);
            codeSmells.setSize(312, 21);
            theContent.add(codeSmells);

            GeneralComboBoxListener listener = new GeneralComboBoxListener(codeSmells, codeSmellGroups, refactorings);
            codeSmellGroups.addActionListener(listener);
            codeSmells.addActionListener(listener);

            this.repaint();
        }
    }

    public static class GeneralComboBoxListener implements ActionListener {

        private JComboBox codeSmells;
        private JComboBox codeSmellGroups;
        private DefaultListModel refactorings;

        public GeneralComboBoxListener(JComboBox codeSmells, JComboBox codeSmellGroups, JList refactorings) {
            if(codeSmells != null)
                this.codeSmells = codeSmells;

            if(codeSmellGroups != null)
                this.codeSmellGroups = codeSmellGroups;

            if(refactorings != null)
                this.refactorings = (DefaultListModel)refactorings.getModel();

            String[] items = new String[] { "", "Bloaters", "Object-Orientation Abusers", "Change Preventers", "Dispensables", "Couplers" };
            addItems(codeSmellGroups, items);
        }

        public void actionPerformed(ActionEvent e) {
            JComboBox sorz = (JComboBox)e.getSource();
            if(sorz.equals(codeSmellGroups)) {
                if(codeSmellGroups.getSelectedItem().equals("Bloaters")) {
                    codeSmells.removeAllItems();
                    refactorings.clear();
                    String[] items = new String[] { "", "Long Method", "Large Class", "Primitive Obsession", "Long Parameter List", "DataClumps" };
                    addItems(codeSmells, items);
                } else if(codeSmellGroups.getSelectedItem().equals("Object-Orientation Abusers")) {
                    codeSmells.removeAllItems();
                    refactorings.clear();
                    String[] items = new String[] { "", "Switch Statements", "Temporary Field", "Refused Request", "Alternative Class with Different Interface" };
                    addItems(codeSmells, items);
                } else if(codeSmellGroups.getSelectedItem().equals("Change Preventers")) {
                    codeSmells.removeAllItems();
                    refactorings.clear();
                    String[] items = new String[] { "", "Divergent Change", "Shotgun Surgery", "Parallel Inheritance Hierarchies" };
                    addItems(codeSmells, items);
                } else if(codeSmellGroups.getSelectedItem().equals("Dispensables")) {
                    codeSmells.removeAllItems();
                    refactorings.clear();
                    String[] items = new String[] { "", "Lazy Class", "Data Class", "Duplicate Code", "Dead Code", "Speculative Generality" };
                    addItems(codeSmells, items);
                } else if(codeSmellGroups.getSelectedItem().equals("Couplers")) {
                    codeSmells.removeAllItems();
                    refactorings.clear();
                    String[] items = new String[] { "", "Feature Envy", "Inappropriate Intimacy", "Message Chains", "Middle Man" };
                    addItems(codeSmells, items);
                }
            } else if(sorz.equals(codeSmells)) {
                if (codeSmellGroups.getSelectedItem().equals("Bloaters")) {
                    if (codeSmells.getSelectedItem() == null) {
                    } else if (codeSmells.getSelectedItem().equals("Long Method")) {
                        refactorings.clear();
                        String[] items = new String[] { "Extract Method", "Introduce Parameter Object", "Decompose Conditional If", "Preserve Whole Object", "Replace Method with Method Object", "Replace Temp with Query" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Large Class")) {
                        refactorings.clear();
                        String[] items = new String[] { "Extract Class", "Extract Subclass", "Extract Interface", "Replace Data Value with Object" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Primitive Obsession")) {
                        refactorings.clear();
                        String[] items = new String[] { "Replace Data Value with Objects", "Introduce Parameter Object", "Extract Class", "Replace Type Code with Class", "Replace Type Code with Subclass", "Replace Array with Object" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Long Parameter List")) {
                        refactorings.clear();
                        String[] items = new String[] { "Replace Parameter with Method", "Introduce Parameter Object", "Preserve Whole Object" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("DataClumps")) {
                        refactorings.clear();
                        String[] items = new String[] { "Extract Class", "Preserve Whole Object", "Introduce Parameter Object" };
                        addItems(refactorings, items);
                    }
                } else if (codeSmellGroups.getSelectedItem().equals("Object-Orientation Abusers")) {
                    if (codeSmells.getSelectedItem() == null) {
                    } else if (codeSmells.getSelectedItem().equals("Switch Statements")) {
                        refactorings.clear();
                        String[] items = new String[] { "Replace Conditional with Polymorphism", "Replace Type Code with Subclass", "Replace Type Code with State/Strategy", "Replace Parameter with Explicit Methods" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Temporary Field")) {
                        refactorings.clear();
                        refactorings.addElement("Extract Class");
                    } else if (codeSmells.getSelectedItem().equals("Refused Request")) {
                        refactorings.clear();
                        String[] items = new String[] { "Push Down Field", "Push Down Method", "Replace Inheritance with Delegation" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Alternative Class with Different Interface")) {
                        refactorings.clear();
                        String[] items = new String[] { "Rename Method", "Move Method" };
                        addItems(refactorings, items);
                    }
                } else if (codeSmellGroups.getSelectedItem().equals("Change Preventers")) {
                    if (codeSmells.getSelectedItem() == null) {
                    } else if (codeSmells.getSelectedItem().equals("Divergent Change")) {
                        refactorings.clear();
                        refactorings.addElement("Extract Class");
                    } else if (codeSmells.getSelectedItem().equals("Shotgun Surgery")) {
                        refactorings.clear();
                        String[] items = new String[] { "Move Method", "Move Field", "Inline Class" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Parallel Inheritance Hierarchies")) {
                        refactorings.clear();
                        String[] items = new String[] { "Move Method", "Move Field" };
                        addItems(refactorings, items);
                    }
                } else if (codeSmellGroups.getSelectedItem().equals("Dispensables")) {
                    if (codeSmells.getSelectedItem() == null) {
                    } else if (codeSmells.getSelectedItem().equals("Lazy Class")) {
                        refactorings.clear();
                        String[] items = new String[] { "Collapse Hierarchy", "Inline Class", "Inline Singleton" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Data Class")) {
                        refactorings.clear();
                        String[] items = new String[] { "Move Method", "Encapsulate Field", "Encapsulate Collection" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Duplicate Code")) {
                        refactorings.clear();
                        refactorings.addElement("Extract Method");
                    } else if (codeSmells.getSelectedItem().equals("Dead Code")) {
                        refactorings.clear();
                        String[] items = new String[] { "Source Control", "Delete It" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Speculative Generality")) {
                        refactorings.clear();
                        String[] items = new String[] { "Collapse Hierarchy", "Rename Method", "Remove Parameter", "Inline Class" };
                        addItems(refactorings, items);
                    }
                } else if (codeSmellGroups.getSelectedItem().equals("Couplers")) {
                    if (codeSmells.getSelectedItem() == null) {
                    } else if (codeSmells.getSelectedItem().equals("Feature Envy")) {
                        refactorings.clear();
                        String[] items = new String[] { "Extract Method", "Move Method", "Move Field" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Inappropriate Intimacy")) {
                        refactorings.clear();
                        String[] items = new String[] { "Move Method", "Move Field", "Change Bidirectional Association to Unidirectional Association", "Extract Class", "Extract Delegate", "Replace Inheritance with Delegation" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Message Chains")) {
                        refactorings.clear();
                        String[] items = new String[] { "Hide Delegate", "Extract Method", "Move Method" };
                        addItems(refactorings, items);
                    } else if (codeSmells.getSelectedItem().equals("Middle Man")) {
                        refactorings.clear();
                        String[] items = new String[] { "Remove Middle Man", "Inline Method", "Replace Delegation with Inheritance" };
                        addItems(refactorings, items);
                    }
                }
            }
        }

        public void addItems(Object listControl, String[] items) {

            if(listControl == null)
                return;

            if(items == null)
                return;

            boolean isComboBox = listControl instanceof JComboBox;
            boolean isListBox = listControl instanceof JList;
            boolean stop = !isComboBox && !isListBox;

            if(stop)
                return;

            for(int i = 0; i < items.length; i++) {
                if(isComboBox)
                {
                    JComboBox addHere = (JComboBox)listControl;
                    addHere.addItem(items[i]);
                    continue;
                }
                if(isListBox)
                {
                    JList theList = (JList)listControl;
                    DefaultListModel addHere = (DefaultListModel)theList.getModel();
                    addHere.addElement(items[i]);
                    continue;
                }
            }
            
        }
    }
}